// NOTE:谨记，涉及到ex级牵扯到的东西较多，如果发生异常，一定要及时取消(一些随着流水线刷的不需要考虑是否取消)

import chisel3._
import chisel3.util._
import config.Configs._
import config.BtbParams._
import Control._
import config.GenCtrl

// EXU（执行单元）模块定义
class EXU extends Module {
  // 定义输入输出端口
  val ex=IO(new Bundle {
    val in=Flipped(new ih_to_ex_bus_bundle()) // 来自上一流水级的输入
    val to_ls=new ex_to_ls_bus_bundle()       // 发送到访存级
    val to_mdu=new to_mul_div_bundle()        // 发送到乘除法单元

    // 各级前递通路
    val fw_pf=Output(new pf_from_ex_bus_bundle())
    val fw_if=Output(new if_from_ex_bus_bundle())
    val fw_id=Output(new id_from_ex_bus_bundle())
    val fw_ih=Output(new ih_from_ex_bus_bundle())
    val from_ls=Input(new ex_from_ls_bus_bundle()) // 来自访存级的反馈
    // val from_csr=Flipped(new ex_with_csr())
    val to_tlb=if(GenCtrl.USE_TLB) Some(Output(new ex_to_mmuctrl_bundle())) else None // TLB相关
    val ctrl_cache=new ctrl_cache_bundle() // cache控制
    val sc=Vec(2,new DataAxiBridgeSendCannel())   // 与cache和TLB交互
  })

  // 异常冲刷信号
  val ex_flush=ex.from_ls.flush.asUInt.orR
  // 指令有效寄存器
  val ex_valid_r=RegInit(VecInit(Seq.fill(2)(false.B)))
  val ex_excp_en=Wire(Vec(2,Bool())) // 异常使能
  val ex_clog=dontTouch(Wire(Vec(2,Bool()))) // 阻塞信号
  val ex_valid=dontTouch(Wire(Vec(2,Bool()))) // 有效信号
  val ex_bits=Wire(Vec(2,new ex_to_ls_bus_data_bundle())) // 传递到下一流水级的数据
  val ex_ready_go=Wire(Vec(2,Bool())) // 是否可以进入下一流水级
  val br_b_taken=Wire(Vec(2,Bool())) // 分支是否被采取
  val flush_second_inst = WireInit(false.B) // 是否需要冲刷第二条指令

  // 时序逻辑：更新指令有效位
  for(i<-0 until 2){
    when(ex_flush){
      ex_valid_r(i):=false.B
    }.elsewhen(ex.in.allowin){
      ex_valid_r(i):=ex.in.dualmask(i)
    }
  }
  // 组合逻辑：计算当前指令是否有效
  for(i<-0 until 2){
    ex_valid(i):=ex_valid_r(i) && ~ex_flush
  }
  // 计算ready信号
  ex_ready_go(0):= ~ex_clog(0)||ex_excp_en(0)
  ex_ready_go(1):= ~ex_clog(1)||ex_excp_en.asUInt.orR
  // 允许新指令进入的条件
  ex.in.allowin:= ~(ex_valid_r(0)||ex_valid_r(1))|| ex_ready_go.asUInt.andR && ex.to_ls.allowin
  // dualmask用于指示哪条指令可以进入下一流水级
  ex.to_ls.dualmask(0):=ex_valid(0)&&ex_ready_go.asUInt.andR
  ex.to_ls.dualmask(1):=ex_valid(1)&&ex_ready_go.asUInt.andR&& ~ex_excp_en(0)&& ~flush_second_inst

//------------------------ 计算单元 ------------------------
  // ALU、乘除法相关信号
  val Alu=Array.fill(2)(Module(new Alu()).io)
  val mul_en=Wire(Vec(2,Bool()))
  val div_en=Wire(Vec(2,Bool()))
  val mdu_signed=Wire(Vec(2,Bool()))
  for(i<-0 until 2){  
    Alu(i).op  :=ex.in.bits(i).alu_op
    Alu(i).src1:=ex.in.bits(i).src1
    Alu(i).src2:=ex.in.bits(i).src2
    mdu_signed(i):=ex.in.bits(i).alu_op===SDEF(MDU_SIGN)
    div_en(i):=ex.in.bits(i).inst_op===SDEF(OP_DIV)&&ex_valid_r(i) 
    mul_en(i):=ex.in.bits(i).inst_op===SDEF(OP_MUL)&&ex_valid_r(i) 
    // 结果选择：跳转、CSR、计数器、ALU
    ex_bits(i).result :=Mux(ex.in.bits(i).br_type(OneHotDef(J_JIRL)),ex.in.bits(i).pc+4.U,
      Mux(ex.in.bits(i).inst_op===SDEF(OP_CSR)||ex.in.bits(i).inst_op===SDEF(OP_CNT),ex.in.bits(i).csr.rdata,Alu(i).result))
  }
  // 乘除法单元接口赋值
  ex.to_mdu.div_en:=div_en.asUInt.orR
  ex.to_mdu.signed:=MuxPriorA(div_en(0)||mul_en(0),mdu_signed)
  ex.to_mdu.src1  :=MuxPriorA(div_en(0)||mul_en(0),ex.in.bits).src1
  ex.to_mdu.src2  :=MuxPriorA(div_en(0)||mul_en(0),ex.in.bits).src2
  ex.to_mdu.divFastSimFlush:=ex_flush // 快速仿真时遇到flush要重置

//------------------------ 计算单元 ------------------------
  // 前递通路赋值
  for(i<-0 until 2){
    ex.fw_ih.bits(i).fw.wen:=ex_valid(i)&&ex.in.bits(i).rf_wen
    ex.fw_ih.bits(i).fw.waddr:=ex.in.bits(i).dest
    ex.fw_ih.bits(i).fw.wdata:=ex_bits(i).result
    ex.fw_ih.bits(i).bypass_unready:=(ex_bits(i).ld_en||ex_bits(i).st_en||ex.in.bits(i).st_type(OneHotDef(ST_SCW))
                                   || mul_en(i)||div_en(i)
                                   || ex_bits(i).relate_src1||ex_bits(i).relate_src2)&&ex_valid(i)
  }

//-----------------------条件分支单元-----------------------
  // 分支跳转相关信号
  val br_target=Wire(Vec(2,UInt(ADDR_WIDTH.W)))
  for(i<-0 until 2){
    var cmp_eq  =(ex.in.bits(i).src1 === ex.in.bits(i).src2)
    var cmp_slt =(ex.in.bits(i).src1.asSInt < ex.in.bits(i).src2.asSInt)
    var cmp_sltu=(ex.in.bits(i).src1  <  ex.in.bits(i).src2)
    br_b_taken(i):=(((ex.in.bits(i).br_type(OneHotDef(BR_BEQ))) &&  cmp_eq)
                  | ((ex.in.bits(i).br_type(OneHotDef(BR_BNE))) && !cmp_eq)
                  | ((ex.in.bits(i).br_type(OneHotDef(BR_BLT))) &&  cmp_slt)
                  | ((ex.in.bits(i).br_type(OneHotDef(BR_BLTU)))&&  cmp_sltu)
                  | ((ex.in.bits(i).br_type(OneHotDef(BR_BGE))) && !cmp_slt)
                  | ((ex.in.bits(i).br_type(OneHotDef(BR_BGEU)))&& !cmp_sltu)
                  | ( ex.in.bits(i).br_type(OneHotDef(J_JIRL))))&&ex_valid(i)
    br_target(i):=Mux(ex.in.bits(i).br_type(OneHotDef(J_JIRL)),ex.in.bits(i).src1+ex.in.bits(i).imm,ex.in.bits(i).pc+ex.in.bits(i).imm)
  }
  
  val taken = br_b_taken.asUInt.orR
  val target = Mux(br_b_taken(0),br_target(0),br_target(1))
  // 预测器相关信号
  val pred = Wire(Vec(FetchWidth, new PredictorOutput()))
  for( i <- 0 until FetchWidth ){
    pred(i) := ex.in.bits(i).pred
  }

  val predictorUpdate = Wire(Vec(FetchWidth, new PredictorUpdate()))
  for( i <- 0 until FetchWidth ){
    predictorUpdate(i).valid := (ex.in.bits(i).isBrCond && ex_valid(i)) // 有效分支需更新
    predictorUpdate(i).pc := ex.to_ls.bits(i).pc
    predictorUpdate(i).brTaken := br_b_taken(i)
    predictorUpdate(i).entry.brTarget := br_target(i)
    predictorUpdate(i).entry.brType   := Mux(ex.in.bits(i).isBrCond, 1.U, 0.U)
  }

  /*
  ih          pred      pred_target   redirect
  |           |         |             |
  taken       taken     target_right  nothing
                        target_wrong  target
              not taken               target
  not taken   taken                   snpc   add 4 or 8?
              not taken               nothing
  */
  // 分支预测正确/错误判断
  val bp_direction_right = Wire(Vec(FetchWidth, Bool()))
  val bp_target_right = Wire(Vec(FetchWidth, Bool()))
  val bp_right = Wire(Vec(FetchWidth, Bool()))
  val bp_wrong = Wire(Vec(FetchWidth, Bool()))
  val bp_wrong_redirect = Wire(Vec(FetchWidth, UInt(ADDR_WIDTH.W)))
  dontTouch(bp_wrong_redirect)
  val bpWRedirectTaken = Wire(Bool())
  val bpWRedirect = WireInit(0.U(ADDR_WIDTH.W))
  for( i <- 0 until FetchWidth ){
    bp_direction_right(i) := pred(i).brTaken === br_b_taken(i)
    bp_target_right(i) := br_b_taken(i) && bp_direction_right(i) && (pred(i).entry.brTarget === br_target(i))

    bp_right(i) := bp_direction_right(i) && (!br_b_taken(i) || bp_target_right(i))
    bp_wrong(i) :=(!bp_direction_right(i) || (br_b_taken(i) && !bp_target_right(i)))&&ex.in.bits(i).isBrCond
    bp_wrong_redirect(i) := Mux(bp_wrong(i) && br_b_taken(i), br_target(i),
                              Mux(bp_wrong(i) && !br_b_taken(i), ex.to_ls.bits(i).pc + 4.U, 0.U)) //
  }
  bpWRedirectTaken := (0 until FetchWidth).map{i => bp_wrong(i) && ex_valid(i) && ex.in.bits(i).isBrCond}.reduce(_ || _)
  bpWRedirect := Mux(bp_wrong(0) && ex_valid(0), bp_wrong_redirect(0), bp_wrong_redirect(1))

  //miss pred and is first inst
  flush_second_inst := bp_wrong(0) && ex.in.bits(0).isBrCond
  // 分支预测错误时的冲刷信号
  ex.fw_pf.br_b.taken := bpWRedirectTaken
  ex.fw_pf.br_b.target := bpWRedirect
  ex.fw_if.br_flush := bpWRedirectTaken
  ex.fw_id.br_flush := bpWRedirectTaken
  ex.fw_ih.br_flush := bpWRedirectTaken
//-----------------------条件分支单元-----------------------
  // 分支预测性能计数器
  val bp_right_counter = RegInit(0.U(ADDR_WIDTH.W))
  val bp_wrong_counter = RegInit(0.U(ADDR_WIDTH.W))
  val bp_isCond_counter = RegInit(0.U(ADDR_WIDTH.W))
  dontTouch(bp_isCond_counter)
  dontTouch(bp_wrong_counter)
  if(GenCtrl.PERF_CNT){
    if(GenCtrl.PERF_CNT){
      when(ex.in.bits(0).isBrCond && ex.to_ls.dualmask(0)){
        bp_isCond_counter := bp_isCond_counter + 1.U
        bp_wrong_counter := Mux(bp_wrong(0) && pred(0).entry.brType === 1.U, bp_wrong_counter + 1.U, bp_wrong_counter)
      }.elsewhen(ex.in.bits(0).isBrCond && ex.to_ls.dualmask(1)){
        bp_isCond_counter := bp_isCond_counter+ 2.U
        bp_wrong_counter := Mux(bp_wrong(0) && pred(0).entry.brType === 1.U, bp_wrong_counter + 2.U, bp_wrong_counter)
      }
      for( i <- 0 until FetchWidth ){
        when(ex.in.bits(i).perf_sys_quit){
          printf("cond_cnt=%d cond_wrong_cnt=%d\n",bp_isCond_counter,bp_wrong_counter)
          printf("miss_rate=%d%%\n",((bp_wrong_counter.asSInt *100.asSInt)/bp_isCond_counter.asSInt))
          printf("---------------------------BTB_PERF---------------------------\n")
        }
      }
    }
  }


//-------------------------- CACOP -------------------------
// CACOP（Cache操作）相关信号定义

// 定义每条指令是否为 CACOP 指令的使能信号（2条指令并行，Vec(2, Bool)）
val ex_cacop_en = Wire(Vec(2, Bool()))

// 定义每条指令是否为 ICACOP（I-Cache操作）指令
val icacop_inst = Wire(Vec(2, Bool()))

// 定义每条指令是否为 DCACOP（D-Cache操作）指令
val dcacop_inst = Wire(Vec(2, Bool()))

// 定义每条指令的 CACOP 操作模式（2位），例如 Index Invalidate、Hit Invalidate 等
val cacop_mode = Wire(Vec(2, UInt(2.W)))

// CACOP 指令是否可以发起 cache 事务的使能信号，主要用于时序控制
val cache_tran_en = Wire(Vec(2, Bool()))

// 标记每条指令是否为 ICACOP 的 mode2 操作（特殊的 I-Cache 操作模式）
val is_icacop2 = Wire(Vec(2, Bool()))

// cache_tran_en 用于控制当前 CACOP 指令是否满足所有条件可以向 cache 发起事务
for (i <- 0 until 2) {
  // 第 i 条指令是否为 CACOP 操作
  ex_cacop_en(i) := (ex.in.bits(i).inst_op === SDEF(OP_CACP))
  // 该指令有效，未发生异常，流水线 ready 且下一级允许进入时，才可以进行 cache 操作
  cache_tran_en(i) := ex_valid(i) && ~ex_excp_en(i) && ex_ready_go.asUInt.andR && ex.to_ls.allowin
  // 判断是否为 ICACOP 指令（即 dest[2:0] == 0）
  icacop_inst(i) := ex_cacop_en(i) && (ex.in.bits(i).dest(2,0) === 0.U)
  // 判断是否为 DCACOP 指令（即 dest[2:0] == 1）
  dcacop_inst(i) := ex_cacop_en(i) && (ex.in.bits(i).dest(2,0) === 1.U)
  // 提取操作 mode（dest[4:3]），决定具体的 cache 操作类型
  cacop_mode(i) := ex.in.bits(i).dest(4,3)
  // 将该指令的 CACOP 使能信号传递到 ex_bits，用于后续流水级
  ex_bits(i).cacop_en := ex_cacop_en(i)
  // 判断是否为 ICACOP 且 mode 为 2 的特殊操作
  is_icacop2(i) := (ex.in.bits(i).dest(4,3) === 2.U) && icacop_inst(i)
}

// DCache 控制信号：
// 只要有一条指令是 DCACOP 并且允许事务发起，就使能 DCache 的 cacop 控制信号
ex.ctrl_cache.dcacop_en := dcacop_inst(0) && cache_tran_en(0) || dcacop_inst(1) && cache_tran_en(1)

// DCache/CACOP 操作模式（优先级选择）：优先选择第0条指令的 cacop_mode，若无则选第1条
ex.ctrl_cache.cacop_mode := MuxPriorA(ex_cacop_en(0), cacop_mode)

// 向前端预测器传递 ICACOP 相关信号：
// 只要有一条指令是 ICACOP 并且 dualmask 允许通过，即通知前端
ex.fw_pf.icacop_en := icacop_inst(0) && ex.to_ls.dualmask(0) || icacop_inst(1) && ex.to_ls.dualmask(1)

// ICACOP 操作的地址选择：
// 如果第0条指令是 load/store 或 CACOP，优先选择第0条的地址，否则选择第1条
ex.fw_pf.icacop_addr := Mux(
  ex.in.bits(0).ld_en || ex.in.bits(0).st_en || ex_cacop_en(0),
  ex_data_addr(0),
  ex_data_addr(1)
)
// ICACOP 操作模式（优先选择第0条指令的 mode）
ex.fw_pf.icacop_mode := MuxPriorA(icacop_inst(0), cacop_mode)
//-------------------------- CACOP -------------------------

//------------------------ 访存单元 ------------------------
  // 访存相关信号
  val ex_data_addr=Wire(Vec(2,UInt(ADDR_WIDTH.W)))
  for(i<-0 until 2){
    ex_bits(i).ld_en:= ex.in.bits(i).ld_en  // 是否是load指令
    ex_bits(i).st_en:= ex.in.bits(i).st_en  // 是否是store指令
    ex_data_addr(i):=ex.in.bits(i).src1+ex.in.bits(i).imm // 访存虚拟地址 由源寄存器1和立即数相加得到（通常是base+offset寻址）
    // 访存指令的低两位地址
    ex_bits(i).addr_low2bit:=Alu(i).result
  }
  // ex级同时只能发起一个访存请求
  // 如果第一条指令是访存或者cacop，执行第一条，否则，执行第二条
  /// ex_final_data_addr:=Mux(ex.in.bits(0).ld_en||ex.in.bits(0).st_en||ex_cacop_en(0),ex_data_addr(0),ex_data_addr(1))
  // 优先第1条指令
  val ex_st_type=Wire(Vec(2,UInt(Control.ST_XX.length.W)))
  val ex_st_src =Wire(Vec(2,UInt(32.W)))
  val mem_size=Wire(Vec(2,UInt(2.W))) // 访问数据宽度类型，高位为半字，低位为字节
  for(i<-0 until 2){
    ex_st_type(i):=ex.in.bits(i).st_type
    ex_st_src(i) :=ex.in.bits(i).src2
    var mem_b_size=(ex_bits(i).ld_type(OneHotDef(LD_LB))||ex_bits(i).ld_type(OneHotDef(LD_LBU))||ex.in.bits(i).st_type(OneHotDef(ST_SB)))
    var mem_h_size=(ex_bits(i).ld_type(OneHotDef(LD_LH))||ex_bits(i).ld_type(OneHotDef(LD_LHU))||ex.in.bits(i).st_type(OneHotDef(ST_SH)))
    mem_size(i):=Cat(mem_h_size,mem_b_size)
  }
  // 最终访存数据宽度类型，优先第一条  高位为半字，低位为字节
  /// val ex_mem_size=Mux(ex.in.bits(0).ld_en||ex.in.bits(0).st_en,mem_size(0),mem_size(1))

  // 写存选择信号
  // 字节写使能选择信号
  val ex_stb_sel=Wire(Vec(2,UInt(4.W)))
  for(i<-0 until 2){
    ex_stb_sel(i) :=Cat(
      ex_data_addr(i)(1,0)===3.U,
      ex_data_addr(i)(1,0)===2.U,
      ex_data_addr(i)(1,0)===1.U,
      ex_data_addr(i)(1,0)===0.U
    )
  }
  // 半字写使能选择信号
  val ex_sth_sel=Wire(Vec(2,UInt(4.W))) 
  for(i<-0 until 2){
    ex_sth_sel(i) :=Cat(
      ex_data_addr(i)(1,0)===2.U,
      ex_data_addr(i)(1,0)===2.U,
      ex_data_addr(i)(1,0)===0.U,
      ex_data_addr(i)(1,0)===0.U
    )
  }
  // 字节写入内容
  val ex_stb_cont=Wire(Vec(2,UInt(32.W)))
  for(i<-0 until 2){
    ex_stb_cont(i) :=Cat( 
      Fill(8,ex_stb_sel(i)(3))&ex_st_src(i)(7,0),
      Fill(8,ex_stb_sel(i)(2))&ex_st_src(i)(7,0),
      Fill(8,ex_stb_sel(i)(1))&ex_st_src(i)(7,0),
      Fill(8,ex_stb_sel(i)(0))&ex_st_src(i)(7,0)
    )
  }
  // 半字写入内容
  val ex_sth_cont=Wire(Vec(2,UInt(32.W)))
  for(i<-0 until 2){
    ex_sth_cont(i) :=Cat(
    Fill(16,ex_sth_sel(i)(3))&ex_st_src(i)(15,0),
    Fill(16,ex_sth_sel(i)(0))&ex_st_src(i)(15,0), 
  )
  }

  val data_wstrb_with_size=Wire(Vec(2,UInt(7.W)))
  val ex_data_size =Wire(Vec(2,UInt(3.W)))
  val ex_data_wstrb=Wire(Vec(2,UInt(4.W)))
  val ex_data_wdata=Wire(Vec(2,UInt(ADDR_WIDTH.W)))
  for(i<-0 until 2){
    data_wstrb_with_size(i) :=(Fill(7,mem_size(i)(0))&Cat(ex_stb_sel(i),0.U(3.W))|
                               Fill(7,mem_size(i)(1))&Cat(ex_sth_sel(i),1.U(3.W))|
                               Fill(7,(!mem_size(i)))&Cat(15.U(4.W) ,2.U(3.W)))
    ex_data_size(i)  :=data_wstrb_with_size(i)(2,0)
    ex_data_wstrb(i) :=data_wstrb_with_size(i)(6,3)
    ex_data_wdata(i) :=(Fill(ADDR_WIDTH,mem_size(i)(0))&ex_stb_cont(i)|
                        Fill(ADDR_WIDTH,mem_size(i)(1))&ex_sth_cont(i)|
                        Fill(ADDR_WIDTH,(!mem_size(i)))&ex_st_src(i))
  }

  for(i<-0 until 2){
    ex_bits(i).is_ll_w:=ex.in.bits(i).ld_type(OneHotDef(LD_LLW))
    ex_bits(i).is_sc_w:=ex.in.bits(i).st_type(OneHotDef(ST_SCW))&&ex.in.bits(i).st_en
  }// 这俩信号是后边判断是否写入llbit的，因此不用加valid

//----------------------- 访存 ----------------------
  // 访存信号
  // 如果第0条指令是store、有效且无异常，允许写；如果第1条是store、有效且没有任何异常且不需要冲刷，也允许写存储
  ex.sc(0).wen:=ex_bits(0).st_en&&ex_valid(0)&& ~ex_excp_en(0)
  ex.sc(1).wen:=ex_bits(1).st_en&&ex_valid(1)&& ~ex_excp_en.asUInt.orR&& ~flush_second_inst
  for(i<-0 until 2){
    ex.sc(i).size:=ex_data_size(i)
    ex.sc(i).addr:=ex_data_addr(i)
    ex.sc(i).wstrb:=ex_data_wstrb(i)  // 写使能字节位
    ex.sc(i).wdata:=ex_data_wdata(i)
  }
  ///ex.sc.size:=ex_data_size
  ///ex.sc.addr:=ex_final_data_addr
  ///ex.sc.wstrb:=ex_data_wstrb  // 写使能字节位
  ///ex.sc.wdata:=ex_data_wdata
  // 如果第0条是load、有效且无异常，允许读；如果第1条是load、有效且没有任何异常且不需要冲刷，也允许读存储
  ex.sc(0).ren:=ex_bits(0).ld_en&&ex_valid(0)&& ~ex_excp_en(0)
  ex.sc(1).ren:=ex_bits(1).ld_en&&ex_valid(1)&& ~ex_excp_en.asUInt.orR && ~flush_second_inst
  // 为了提升双发率，允许第一条为bru时双发，只不过要主动取消
  // 假设有bug，第一条异常第二条访存，此时取消第二条访存请求
  for(i<-0 until 2){
    ex_clog(i):=((( ~ex.sc(i).addr_ok&&ex_bits(i).st_en&& ~flush_second_inst)
                ||( ~ex.sc(i).addr_ok&&ex_bits(i).ld_en&& ~flush_second_inst)
                ||( ~ex.sc(i).addr_ok&&dcacop_inst(i)  && ~flush_second_inst)
                ||( div_en(i)&& ~ex.to_mdu.div_ok))&&ex_valid(i))
  }
  for(i<-0 until 2){
    ex.sc(i).addr_en:=(((ex.sc(i).wen||ex.sc(i).ren)||dcacop_inst.asUInt.orR)&&ex.sc(i).addr_ok 
                ||(is_icacop2.asUInt.orR||ex.to_tlb.get.tlbsrch_en&&ex_ready_go.asUInt.orR&&ex.to_ls.allowin))
  }
  ///ex.sc.addr_en:=(((ex.sc.wen||ex.sc.ren)||dcacop_inst.asUInt.orR)&&ex.sc.addr_ok 
                ///||(is_icacop2.asUInt.orR||ex.to_tlb.get.tlbsrch_en&&ex_ready_go.asUInt.orR&&ex.to_ls.allowin))
  // 当addr_ok时才对tlb发起访存请求，保证tlb得出tag后cache正好需要对比tag
//----------------------- 访存 ----------------------

//--------------------------  CSR -------------------------
  // CSR相关信号
  for(i<-0 until 2){
    ex_bits(i).csr.op :=ex.in.bits(i).csr.op
    ex_bits(i).csr.wen:=ex.in.bits(i).csr.wen
    ex_bits(i).csr.addr:=ex.in.bits(i).csr.addr
    var csrWdataMap=Map(
      SDEF(CSR_WR)    -> ex.in.bits(i).src2,
      SDEF(CSR_XCHG)  -> ((ex.in.bits(i).src2&ex.in.bits(i).src1)|(ex.in.bits(i).csr.rdata& ~ex.in.bits(i).src1)),
    )
    ex_bits(i).csr.wdata:=Mux1hMap(ex_bits(i).csr.op,csrWdataMap)
    ex_bits(i).csr.ertn_en:=ex.in.bits(i).csr.op===SDEF(CSR_ERTN)&&ex_valid(i)
    ex_bits(i).csr.idle_en:=ex.in.bits(i).inst_op===SDEF(OP_IDLE)&&ex_valid(i)
  }
//--------------------------  CSR -------------------------
//--------------------------  TLB -------------------------
  // TLB相关信号
  if(GenCtrl.USE_TLB){
    // TLB查找使能
    ex.to_tlb.get.tlbsrch_en:=(ex.in.bits(0).csr.op===SDEF(TLB_SRCH)&&ex_valid(0)&& ~ex_excp_en(0)
                             ||ex.in.bits(1).csr.op===SDEF(TLB_SRCH)&&ex_valid(1)&& ~ex_excp_en(1))
    // 当前是否有任意一条指令为TLB_SRCH操作
    ex.to_tlb.get.is_tlbsrch:=(ex.in.bits(0).csr.op===SDEF(TLB_SRCH)||ex.in.bits(1).csr.op===SDEF(TLB_SRCH))
  }
  for(i<-0 until 2){
    ex_bits(i).invtlb.asid:=ex.in.bits(i).src1(9,0)
    ex_bits(i).invtlb.va  :=ex.in.bits(i).src2(31,13)
    ex_bits(i).tlb_refetch:=ex.in.bits(i).inst_op===SDEF(OP_TLB)
  }
//--------------------------  TLB -------------------------
//------------------------ 访存单元 ------------------------
  // 异常相关信号
  val ex_excp_type=Wire(Vec(2,new ex_excp_bundle()))
  for(i<-0 until 2){
    ex_excp_en(i):=ex_excp_type(i).asUInt.orR
    ex_excp_type(i).ale:=(((mem_size(i)(1)&&ex_data_addr(i)(0)) ||
                          (!mem_size(i)   &&ex_data_addr(i)(1,0).asUInt.orR))&&
                          (ex_bits(i).ld_en||ex_bits(i).st_en)&& ~flush_second_inst)
    ex_excp_type(i).num:=ex.in.bits(i).excp_type
  }

  // 延迟相关信号
  ex_bits(0).delay_alu_op:=DontCare
  ex_bits(0).relate_src1:=DontCare
  ex_bits(0).relate_src2:=DontCare
  ex_bits(0).delay_src1:=DontCare
  ex_bits(0).delay_src2:=DontCare
  ex_bits(1).delay_alu_op:=ex.in.bits(1).alu_op
  ex_bits(1).relate_src1:=ex.in.bits(1).relate_src1
  ex_bits(1).relate_src2:=ex.in.bits(1).relate_src2
  ex_bits(1).delay_src1:=ex.in.bits(1).src1
  ex_bits(1).delay_src2:=ex.in.bits(1).src2

//NOTE:perf
  // 性能相关信号
  for(i<-0 until 2){
    ex_bits(i).perf_sys_quit:=ex.in.bits(i).perf_sys_quit
    ex_bits(i).perf_branch.taken:=ex.in.bits(i).perf_branch.taken||br_b_taken(i)
    ex_bits(i).perf_branch.br_type:=ex.in.bits(i).br_type 
  }

  for(i<-0 until 2){
    ex_bits(i).isBrJmp :=ex.in.bits(i).isBrJmp
    ex_bits(i).isBrCond:=ex.in.bits(i).isBrCond
    ex_bits(i).brjump_result:=ex.in.bits(i).brjump_result
    ex_bits(i).brcond_result:=predictorUpdate(i)
  }
//------------------------流水级总线------------------------
  // diff相关信号
  val loadValid=Wire(Vec(2,UInt(8.W))) // 用来diff
  val storeValid=Wire(Vec(2,UInt(8.W)))
  val realLoadValid=Wire(Vec(2,UInt(8.W)))
  val realStoreValid=Wire(Vec(2,UInt(8.W)))
  for(i<-0 until 2){
    loadValid(i):= Cat(0.U(2.W),ex.in.bits(i).ld_type(OneHotDef(LD_LLW)),
                                ex.in.bits(i).ld_type(OneHotDef(LD_LW)),
                                ex.in.bits(i).ld_type(OneHotDef(LD_LHU)),
                                ex.in.bits(i).ld_type(OneHotDef(LD_LH)),
                                ex.in.bits(i).ld_type(OneHotDef(LD_LBU)),
                                ex.in.bits(i).ld_type(OneHotDef(LD_LB)))
    storeValid(i):=Cat(0.U(4.W),ex.in.bits(i).st_type(OneHotDef(ST_SCW))&&ex_bits(i).st_en,
                                ex.in.bits(i).st_type(OneHotDef(ST_SW)),
                                ex.in.bits(i).st_type(OneHotDef(ST_SH)),
                                ex.in.bits(i).st_type(OneHotDef(ST_SB))) 
  }
  realLoadValid(0):=loadValid(0)
  realLoadValid(1):=Mux(ex_bits(0).ld_en||ex_bits(0).st_en,0.U,loadValid(1))
  realStoreValid(0):=storeValid(0)
  realStoreValid(1):=Mux(ex_bits(0).ld_en||ex_bits(0).st_en,false.B,storeValid(1))
  for(i<-0 until 2){
    ex_bits(i).diffLoad.valid:=realLoadValid(i)
    ex_bits(i).diffLoad.paddr:=DontCare
    ex_bits(i).diffLoad.vaddr:=ex_data_addr(i)

    ex_bits(i).diffStore.valid:=realStoreValid(i)
    ex_bits(i).diffStore.paddr:=DontCare
    ex_bits(i).diffStore.vaddr:=ex_data_addr(i)
    ex_bits(i).diffStore.data :=ex_data_wdata(i)
  }

  // diffInstr相关信号
  for(i<-0 until 2){
    ex_bits(i).diffInstr.is_CNTinst:=ex.in.bits(i).diffInstr.is_CNTinst
    ex_bits(i).diffInstr.csr_rstat :=ex.in.bits(i).diffInstr.csr_rstat
    ex_bits(i).diffInstr.csr_data  :=ex.in.bits(i).csr.rdata
    ex_bits(i).diffInstr.timer64value:=ex.in.bits(i).diffInstr.timer64value

    ex_bits(i).excp_en:=ex_excp_en(i)
    ex_bits(i).excp_type:=ex_excp_type(i)
    ex_bits(i).bad_addr:=ex_data_addr(i)
    ex_bits(i).ld_type:=ex.in.bits(i).ld_type
    ex_bits(i).wb_sel :=ex.in.bits(i).wb_sel
    ex_bits(i).rf_wen :=ex.in.bits(i).rf_wen
    ex_bits(i).rf_addr:=ex.in.bits(i).dest
    ex_bits(i).inst   :=ex.in.bits(i).inst
    ex_bits(i).pc     :=ex.in.bits(i).pc  
  }
  ex_bits(0).pred := pred(0)
  ex_bits(1).pred := pred(1)
  ex.to_ls.bits:=ex_bits

}

// cache控制信号定义
class ctrl_cache_bundle() extends Bundle{
  val dcacop_en=Output(Bool())
  val cacop_mode=Output(UInt(2.W))
}